unit main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, DBTables, StdCtrls, ComCtrls, ShellAPI, strUtils;

type
  TfrmMain = class(TForm)
    grpProg: TGroupBox;
    prgTotal: TProgressBar;
    prgSteps: TProgressBar;
    lblUpdProg: TLabel;
    btnUpdCanc: TButton;
    tblVer: TTable;
    tblVerVersion: TFloatField;
    tblSettings: TTable;
    tblSettingsOptAutoUpdate: TBooleanField;
    tblSettingsOptAutoEmpty: TBooleanField;
    tblSettingsOptAutoArchive: TBooleanField;
    tblSettingsOptAutoMove: TBooleanField;
    tblSettingsOptAutoMoveDir: TStringField;
    procedure FormShow(Sender: TObject);
  private
    procedure ExtractRes(ResName, Output: string);
    procedure BackupFiles(CopyFrom, CopyTo, CopyMask: String);
    procedure FieldAdd(Table: TTable; SQLTbl, FldName, FldType: string);
    procedure NotNull(SQLTable, SQLField: string);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmMain:   TfrmMain;
  lvSource:  string;
  lvDest:    string;
  lvSourceW: PWideChar;
  lvDestW:   PWideChar;
  lvDate:    string;
  lvVer:     Double;

implementation

{$R *.dfm}

procedure TfrmMain.FormShow(Sender: TObject);
begin
  // Version
  lvVer := 1.45;

  // Set current date
  lvDate   := StringReplace(DateTimeToStr(Date), '/', '-', [rfReplaceAll, rfIgnoreCase]);

  // Set current dir
  lvSource := GetCurrentDir + '\System';
  lvDest   := GetCurrentDir + '\Backups\' + lvDate;

{$REGION 'Backup existing files'}
  lblUpdProg.Caption := 'Backing up existing tables...';
    BackupFiles(lvSource, lvDest, '*.*');
{$ENDREGION}

{$REGION 'Add/Remove Fields'}
  lblUpdProg.Caption := 'Adding/Modifying fields...';
    // No Fields to add yet!

{$ENDREGION}

{$REGION 'Update Executable Files'}
  lblUpdProg.Caption := 'Extracting/Renaming executables...';
    if FileExists('GIPM.exe') then
      RenameFile('GIPM.exe', 'oldGIPM.exe');

    ExtractRes('GIPMExe', GetCurrentDir + '/' + 'GIPM.exe');
{$ENDREGION}

{$REGION 'Perform Cleanup'}
  lblUpdProg.Caption := 'Performing cleanup...';
    DeleteFile('oldGIPM.exe');
{$ENDREGION}

  // Update version in system table
  tblVer.Open;
  tblVer.Edit;
    tblVerVersion.AsFloat := lvVer;
  tblVer.Post;
  tblVer.Close;

  lblUpdProg.Caption := 'Update Finished, starting GIPM...';

  ShellExecute(Application.Handle, PChar('open'), PChar('GIPM.EXE'),
      PChar(''), nil, SW_NORMAL);

  Application.Terminate;
end;

{$REGION 'Custom Fucntions/Procedures'}
procedure TfrmMain.FieldAdd(SQLTbl, FldName, FldType: string);
var
  Qry: TQuery;
begin
  try
    with Qry := TQuery.Create(Application) do
    begin
      Qry.Close;
      Qry.SQL.Text := 'ALTER TABLE '+SQLTbl+' ADD '+FldName+' '+FldType;
      Qry.ExecSQL;
    end;
    NotNull(SQLTbl, FldName);
  except
    On E : Exception do
    begin
      ShowMessage('Updating tables failed with the following error: ' + E.Message + #13#10 + #13#10 +
                  'Backup will be restored and update cancelled.');

      BackupFiles(lvDest, lvSource, '*.*');
      ShowMessage('Backup has been restored, closing update.');
      Application.Terminate;
    end;
  end;
end;

procedure TfrmMain.NotNull(SQLTable, SQLField: string);
begin
  try
    with TQuery.Create(nil) do
    begin
      DatabaseName := 'GIPM';
      Close;
      SQL.Text := 'UPDATE '+SQLTable+' X SET X.' + SQLField + ' = ''FALSE''';
      ExecSQL;
    end;
  finally
    Free;
  end;
end;

procedure TfrmMain.ExtractRes(ResName, Output: string);
var
  ExeOutput: TResourceStream;
begin
    ExeOutput := TResourceStream.Create(HInstance, ResName, RT_RCDATA);
    try
      ExeOutput.Position := 0;
      ExeOutput.SaveToFile(Output);
    finally
      ExeOutput.Free;
    end;
end;

procedure TfrmMain.BackupFiles(CopyFrom, CopyTo, CopyMask: String);
var
FO: TSHFileOpStruct;
begin
  if Not DirectoryExists(CopyFrom) Then Exit;

  FO.Wnd := Application.Handle;
  FO.wFunc := FO_COPY;
  FO.pFrom := PChar(IncludeTrailingBackSlash(CopyFrom) + CopyMask + #0#0);
  FO.pTo := PChar(IncludeTrailingBackSlash(CopyTo) + #0#0);
  FO.fFlags := FOF_NOCONFIRMATION Or FOF_NOCONFIRMMKDIR Or FOF_SILENT Or FOF_ALLOWUNDO;
  ShFileOperation(FO);
end;
{$ENDREGION}

end.
